package sqlInject;

import beans.ErrorPayload;
import beans.OrdinaryPayload;
import beans.ResponseInfo;
import burp.*;
import result.AttackResult;
import result.ModelRoot;
import sqlInject.api.ISqlInjectType;
import ui.Model;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.Callable;

/**
 * Created by shuaidong on 2017/6/25.
 */
public class SqlInjectType implements ISqlInjectType,Callable<IScanIssue> {
    public static enum InjectType{
        ERRORINJECT, ORDINARYINJECTION, SQLBINDINJECT
    }
    private InjectType injectType;
    private IHttpRequestResponse iHttpRequestResponse;
    private IBurpExtenderCallbacks callbacks;
    private  List<IScannerInsertionPoint>  scannerInsertionPoints;


    public SqlInjectType(InjectType injectType,IHttpRequestResponse iHttpRequestResponse,
                         IBurpExtenderCallbacks callbacks,
                         List<IScannerInsertionPoint> insertionPoints) {
        this.injectType = injectType;
        this.iHttpRequestResponse = iHttpRequestResponse;
        this.callbacks = callbacks;
        this.scannerInsertionPoints = insertionPoints;

    }

    public IScanIssue errorInject() {

            IRequestInfo requestInfo = callbacks.getHelpers().analyzeRequest(iHttpRequestResponse);
            boolean isInject = false;
         /*   try {
                this.callbacks.getStdout().write("error开始注入".getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }*/

            //  byte[] response = this.iHttpRequestResponse.getResponse();

            ResponseInfo responseInfo = new ResponseInfo(this.callbacks.getHelpers());
            responseInfo = responseInfo.getResponseInfo(iHttpRequestResponse);


            List<ErrorPayload> errorPayloads = Model.getInstanceModel().getErrorPayloadList();
            for (IScannerInsertionPoint insertionPoint:scannerInsertionPoints){

                Iterator<ErrorPayload> errorPayloadIterator = errorPayloads.iterator();
                while (errorPayloadIterator.hasNext()){

                    ErrorPayload errorPayload = errorPayloadIterator.next();

                    byte[] mistakeThinkRequst = insertionPoint.buildRequest(errorPayload.getLeadingMistakeContent().getBytes());

                    IHttpRequestResponse mistakeThinkIhttpRequestResponse = callbacks.makeHttpRequest(
                            iHttpRequestResponse.getHttpService(), mistakeThinkRequst);
                   ResponseInfo mistakeThinkResponse = new ResponseInfo(this.callbacks.getHelpers());
                   mistakeThinkResponse = mistakeThinkResponse.getResponseInfo(mistakeThinkIhttpRequestResponse);

                    for (String mistakeFlag:errorPayload.getMistakeContentFlag()){
                      /*  try {
                            this.callbacks.getStdout().write("匹配erroryPayload".getBytes());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }*/
                        if (!responseInfo.getResponse_content().contains(mistakeFlag)&&
                                mistakeThinkResponse.getResponse_content().contains(mistakeFlag)){
                                isInject = true;

                              //  this.callbacks.getStdout().write("this is maybe inject ...".getBytes());
                                //
                                AttackResult attackResult = new AttackResult(requestInfo.getUrl(),"errorInject",
                                        insertionPoint.getInsertionPointName(),"",
                                        errorPayload.getLeadingMistakeContent(),iHttpRequestResponse);
                                ModelRoot.getModelRootInstance().addAttackResult(attackResult);

                                ScanIssue scanIssue = new ScanIssue(this.iHttpRequestResponse,this.callbacks,
                                        "high","ErrorSqlinject","SQLInject",mistakeFlag);
                                return scanIssue;

                        }
                    }

                }

            }


        return null;
    }

    public IScanIssue ordinaryInjection() {
        boolean isInject = false;

        ResponseInfo responseInfo = new ResponseInfo(this.callbacks.getHelpers());
        responseInfo = responseInfo.getResponseInfo(iHttpRequestResponse);

      //  List<HashMap<String,String>> payloads = Payload.OrdinaryInjectionPayload.payloads;
        List<OrdinaryPayload> ordinaryPayloadList = Model.getInstanceModel().getOrdinaryPayloadList();


        for (IScannerInsertionPoint insertionPoint:scannerInsertionPoints) {
          /*  try {
                this.callbacks.getStdout().write(("ordinary插入点:"+insertionPoint.getBaseValue()+"\n").getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }*/
            Iterator<OrdinaryPayload> iterator = ordinaryPayloadList.iterator();

            while (iterator.hasNext()&&!isInject) {

                OrdinaryPayload payload = iterator.next();

                byte[] requestThinkNormal = insertionPoint.buildRequest(payload.getPageNormalPayload().getBytes());
              /*  try {
                    this.callbacks.getStdout().write(("普通注入的payload:").getBytes());
                    this.callbacks.getStdout().write(requestThinkNormal);
                } catch (IOException e) {
                    e.printStackTrace();
                }*/

                /*    try {
                        this.callbacks.getStdout().write(requestThinkNormal);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }*/

                    IHttpRequestResponse requestResponseThinkNormal = callbacks.makeHttpRequest(this.iHttpRequestResponse.
                            getHttpService(),requestThinkNormal);
                    ResponseInfo responseInfoThinkNormal = new ResponseInfo(this.callbacks.getHelpers());

                    responseInfoThinkNormal = responseInfoThinkNormal.getResponseInfo(requestResponseThinkNormal);

                    byte[] requestThinkAbnormal = insertionPoint.buildRequest(payload.getPageAbNormalPayload().getBytes());

                    IHttpRequestResponse requestResponseThinkAbmormal = callbacks.makeHttpRequest(this.iHttpRequestResponse.
                            getHttpService(),requestThinkAbnormal);
                    ResponseInfo responseInfoThinkAbNormal = new ResponseInfo(this.callbacks.getHelpers());
                    responseInfoThinkAbNormal = responseInfoThinkAbNormal.getResponseInfo(requestResponseThinkAbmormal);
                if (responseInfo.getUnionAttriute().equals(responseInfoThinkNormal.getUnionAttriute())&&
                            !responseInfoThinkNormal.getUnionAttriute().equals(responseInfoThinkAbNormal.getUnionAttriute())){
                        isInject = true;

                            //IScanIssue iScanIssue = new ScanIssue()

                         /*   this.callbacks.getStdout().write("this is maybe inject ....".getBytes());
                            this.callbacks.getStdout().write(requestThinkNormal);
                            this.callbacks.getStdout().write("\n".getBytes());*/

                            AttackResult attackResult = new AttackResult(this.callbacks.getHelpers().analyzeRequest(iHttpRequestResponse).getUrl(),
                                    "ordinaryInjection",insertionPoint.getInsertionPointName(),payload.getPageNormalPayload(),payload.getPageAbNormalPayload(),requestResponseThinkNormal);
                           // BurpExtender.attackResultList.add(attackResult);
                            ModelRoot.getModelRootInstance().getModelRootInstance().addAttackResult(attackResult);
                            // this.callbacks.getStdout().write("开发".getBytes());



                            ScanIssue scanIssue = new ScanIssue(this.iHttpRequestResponse,this.callbacks,
                                    "high","sqlinject","SQLInject",payload.getPageNormalPayload());
                            return scanIssue;


                    }

            //    }
            }
        }


        return null;
    }

    public IScanIssue sqlBindInject() {
        return null;
    }




    public IScanIssue call() throws Exception {
        switch (injectType){
            case ERRORINJECT:
                return errorInject();
            case SQLBINDINJECT:
                return sqlBindInject();
            case ORDINARYINJECTION:
                return ordinaryInjection();
            default:
                break;
        }
        return null;
    }

    public static void main(String[] args) {

       List<OrdinaryPayload>  list = Model.getInstanceModel().getOrdinaryPayloadList();
       Iterator<OrdinaryPayload> iterator = list.iterator();
       while (iterator.hasNext()){
           OrdinaryPayload payload = iterator.next();
           System.out.println(payload.getPageNormalPayload());
       }
    }
}
